package com.yanqu.road.logic.xlogic.rank.user;

import com.yanqu.road.entity.rank.xrank.XUserRank;
import com.yanqu.road.logic.bussiness.rank.XRankBussiness;
import com.yanqu.road.logic.pb.PlayerBasePb;
import com.yanqu.road.logic.xlogic.rank.base.AbstractXRankListModel;
import com.yanqu.road.logic.xlogic.rank.user.entiety.XGetUserRankResult;
import com.yanqu.road.logic.xlogic.rank.user.entiety.XUserRankChangeParam;
import com.yanqu.road.logic.xlogic.rank.user.entiety.XUserRankChangeResult;

import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

public class XUserRankListModel extends AbstractXRankListModel {

    private int activityId;
    private int conditionType;
    private int maxRank;
    private Comparator<XUserRank> rankSort;

    private LinkedList<XUserRank> rankList = new LinkedList<>();
    private int rankCapacity;

    private long allSyncTime;

    public XUserRankListModel(String dbName, String tableName,
                              int activityId, int conditionType, int maxRank, Comparator<XUserRank> rankSort) {
        super(dbName, tableName);

        this.activityId = activityId;
        this.conditionType = conditionType;
        this.maxRank = maxRank;
        this.rankSort = rankSort;

        this.rankCapacity = calcRankCapacity(maxRank);
    }

    private int calcRankCapacity(int maxRank) {
        return maxRank + 20;
    }

    public void setMaxRank(int maxRank) {
        this.maxRank = maxRank;
        this.rankCapacity = calcRankCapacity(maxRank);
    }

    /**
     * 获取排名
     *
     * @param rankList 超出这个的长度排名为-1
     */
    private XGetUserRankResult getMyRankResult(long userId, List<XUserRank> rankList) {
        int rank = 0;
        for (XUserRank userRank : rankList) {
            rank++;
            if (userRank.getUserId() == userId) {
                return new XGetUserRankResult(userRank, rank);
            }
        }
        return new XGetUserRankResult();
    }

    public int getMyRank(long userId) {
        return getMyRankResult(userId, getRankList()).getMyRank();
    }

    public XUserRankChangeResult rankChange(XUserRank userRank, XUserRankChangeParam param) {
        synchronized (this) {

            boolean isChange = false;
            boolean inList = false;
            XGetUserRankResult oldRankResult = getMyRankResult(userRank.getUserId(), rankList);
            XUserRank oldUserRank = oldRankResult.getUserRank();

            // 更新请求参数
            if (oldUserRank != null) {
                // baseInfo有增量用增量
                userRank.setBaseInfo(
                        param.isUpdateBaseInfo() ?
                                PlayerBasePb.getUpdateUserBaseInfo(oldUserRank.getBaseInfo(), param.getBaseInfoMsg())
                                : userRank.getBaseInfo());
                // 值没变化不改更新时间
                userRank.setLastUpdateTime(rankSort.compare(userRank, oldUserRank) != 0 ? userRank.getLastUpdateTime() : oldUserRank.getLastUpdateTime());
            }

            // 有旧的就替换
            if (oldUserRank != null) {
                oldUserRank.replace(userRank);
                inList = true;
                isChange = true;
            }

            // 能否新上榜
            if (!inList) {
                if (rankList.size() < rankCapacity) {
                    rankList.add(userRank.clone());
                    isChange = true;
                } else {
                    XUserRank lastRank = rankList.getLast();
                    if (rankSort.compare(lastRank, userRank) > 0) {
                        rankList.removeLast();
                        rankList.add(userRank.clone());
                        isChange = true;
                    }
                }
            }

            // 处理结果
            if (isChange) {
                rankList.sort(rankSort);
                int newRank = getMyRankResult(userRank.getUserId(), rankList).getMyRank();
                addDbRank(oldRankResult.getMyRank(), newRank, rankCapacity);
            }

            // 记录结果
            XUserRankChangeResult result = new XUserRankChangeResult();
            result.setChange(isChange);
            result.setNewInRank(isChange && !inList);
            return result;
        }
    }

    public void initByRankList(LinkedList<XUserRank> rankList) {
        synchronized (this) {
            this.rankList = rankList;
            this.rankList.sort(rankSort);
            // 去掉多余的
            while (this.rankList.size() > rankCapacity) {
                this.rankList.removeLast();
            }
        }
    }

    public List<XUserRank> getRankList() {
        return getRankList(maxRank);
    }

    public List<XUserRank> getRankList(int topCount) {
        List<XUserRank> list = new LinkedList<>();
        for (XUserRank rank : new LinkedList<>(rankList)) {
            if (list.size() >= topCount) {
                break;
            }
            list.add(rank);
        }
        return list;
    }

    public List<XUserRank> getAllRankList() {
        return new LinkedList<>(rankList);
    }

    public int getActivityId() {
        return activityId;
    }

    public int getConditionType() {
        return conditionType;
    }

    public int getMaxRank() {
        return maxRank;
    }

    public Comparator<XUserRank> getRankSort() {
        return rankSort;
    }

    public long getAllSyncTime() {
        return allSyncTime;
    }

    public void setAllSyncTime(long allSyncTime) {
        this.allSyncTime = allSyncTime;
    }

    @Override
    public void save() {
        List<XUserRank> tmpRankList;
        Set<Integer> dbRankSet;
        synchronized (this) {
            tmpRankList = new LinkedList<>(rankList);
            dbRankSet = getAndClearAllDbRank();
        }
        // 根据dbName和tableName入库
        XRankBussiness.replaceXUserRank(dbName, tableName, tmpRankList, dbRankSet);
    }

}
